package com.aloda.service.impl;

import com.aloda.constant.*;
import com.aloda.context.BaseContext;
import com.aloda.dto.*;
import com.aloda.entity.Employee;
import com.aloda.exception.*;
import com.aloda.mapper.EmpMapper;
import com.aloda.properties.JwtProperties;
import com.aloda.result.PageResult;
import com.aloda.service.EmpService;
import com.aloda.utils.JwtUtil;
import com.aloda.vo.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class EmpServiceImpl implements EmpService {

    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 员工后台登录
     *
     * @param employeeLoginDTO
     */
    @Override
    public EmployeeLoginVO empLogin(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        Employee employee = empMapper.getEmpByUsername(username);

        if(employee==null){
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        // TODO 后期需要进行md5加密，然后再进行比对 //已修改
        //
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if(!Objects.equals(password, employee.getPassword())){
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        //员工状态 注销状态 和 锁定状态 都不可以进行登录
        if(Objects.equals(employee.getAuthority(), AuthorityConstant.LOGOUT)){
            throw new LogoutException(MessageConstant.LOGOUT_ABNORMAL);
        }else if (Objects.equals(employee.getStatus(), StatusConstant.DISABLE)){
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //登录成功后，生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        return EmployeeLoginVO.builder()
                .id(employee.getId())
                .username(employee.getUsername())
                .avatarUrl(employee.getAvatarUrl())
                .token(token)
                .build();
    }

    /**
     * 当前登录者的权限
     * TODO 接收id但不使用，利用线程和jwt方法取出当前登录用户id,两者可以比较
     *
     * @param id
     * @return
     */
    @Override
    public AuthVO getEmpAuth(Long id) {
        //对比前端传递的id和当前线程中保存的id
        if(!Objects.equals(id, BaseContext.getCurrentId())){
            throw new IdError(MessageConstant.ID_ABNORMAL);
        }
        //通过对比后的id查找出当前登录的用户
        Long tureId = BaseContext.getCurrentId();
        Employee employee = empMapper.getEmpById(tureId);
        //把当前用户的权限赋给VO对象并返回
        return AuthVO.builder()
                .authority(employee.getAuthority())
                .build();
    }

    /**
     * 个人信息设置回显
     *
     * @return
     */
    @Override
    public EmployeeSetVO getEmpSetInfo() {
        Long tureId = BaseContext.getCurrentId();
        Employee employee = empMapper.getEmpById(tureId);
        return EmployeeSetVO.builder()
                .avatarUrl(employee.getAvatarUrl())
                .username(employee.getUsername())
                .phone(employee.getPhone())
                .build();
    }

    /**
     * 员工修改个人信息
     *
     * @param
     */
    @Override
    public void empModifyInfo( EmployeeModifyDTO employeeModifyDTO) {
        //先判断个人信息是否修改，若没有修改返回未修改个人信息
        Long id = BaseContext.getCurrentId();
        Employee employee =empMapper.getEmpById(id);
        if(Objects.equals(employeeModifyDTO.getUsername(), employee.getUsername())
                && Objects.equals(employeeModifyDTO.getAvatarUrl(), employee.getAvatarUrl())
                && Objects.equals(employeeModifyDTO.getPhone(), employee.getPhone())){
            throw new ModifyException(MessageConstant.MODIFY_ABNORMAL);
        }
//        //TODO 判断个人信息的合法性，不合法抛出的sql异常已经由全局异常处理器捕获，这里不再需要抛出
//        if(empMapper.getEmpByUsername(employeeModifyDTO.getUsername())!=null){
//            throw new
//        }

        //若修改了个人信息对信息进行更新
        BeanUtils.copyProperties(employeeModifyDTO,employee);
        employee.setUpdateTime(LocalDateTime.now());
        empMapper.updateEmpInfo(employee);
    }

    /**
     * 员工修改密码
     *
     * @param modifyPwdDTO
     */
    @Override
    public void empModifyPwd(ModifyPwdDTO modifyPwdDTO) {
        Long id = BaseContext.getCurrentId();
        Employee employee = empMapper.getEmpById(id);
        String oldPassword =  DigestUtils.md5DigestAsHex(modifyPwdDTO.getOldPassword().getBytes());
        if(!Objects.equals(oldPassword, employee.getPassword())){
            throw new PasswordErrorException(MessageConstant.OLD_PASSWORD_ERROR);
        }
        String newPassword = DigestUtils.md5DigestAsHex(modifyPwdDTO.getNewPassword().getBytes());
        employee.setPassword(newPassword);
        empMapper.updateEmpInfo(employee);
    }

    /**
     * 员工分页查询
     *
     * @return
     */
    @Override
    public PageResult empPage(EmployeePageDTO employeePageDTO) {
        //转化为北京时间
        if (employeePageDTO.getBegin() != null && employeePageDTO.getEnd() != null) {
            employeePageDTO.setBegin(employeePageDTO.getBegin().plusHours(8));
            employeePageDTO.setEnd(employeePageDTO.getEnd().plusHours(8));
        }

        //用page helper插件进行分页查询
        PageHelper.startPage(employeePageDTO.getPage(),employeePageDTO.getPageSize());
        Page<EmployeePageVO> page=empMapper.page(employeePageDTO);
        PageResult pageResult = new PageResult(page.getTotal(),page.getResult());
        return pageResult;
    }

    /**
     * 新增员工
     *
     * @param employeeAddDTO
     */
    @Override
    public void addEmp(EmployeeAddDTO employeeAddDTO) {
        Employee employee=new Employee();
        BeanUtils.copyProperties(employeeAddDTO,employee);
        //默认密码 TODO 注意将默认密码进行md5加密转化
        String pwd = DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes());
        employee.setPassword(pwd);
        //默认权限
        employee.setAuthority(DefaultConstant.DEFAULT_AUTHORITY);
        //默认状态
        employee.setStatus(DefaultConstant.DEFAULT_STATUS);
        //TODO 设置创建时间等公共字段，后期考虑采用自动注入
        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());
        String username = empMapper.getEmpUsernameById(BaseContext.getCurrentId());
        employee.setCreateUser(username);
        employee.setUpdateUser(username);

        empMapper.insert(employee);
    }

    /**
     * 根据id获取员工编辑页面数据
     *
     * @param id
     * @return
     */
    @Override
    public EmployeeEditVO getEmpById(Long id) {
        Employee employee = empMapper.getEmpById(id);
        EmployeeEditVO employeeEditVO=new EmployeeEditVO();
        BeanUtils.copyProperties(employee,employeeEditVO);
        return employeeEditVO;
    }

    /**
     * 更新员工信息
     *
     * @param employeeEditDTO
     */
    @Override
    public void updateEmp(EmployeeEditDTO employeeEditDTO) {
        Employee employee = new Employee();
        BeanUtils.copyProperties(employeeEditDTO,employee);
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(empMapper.getEmpUsernameById(BaseContext.getCurrentId()));
        if(Objects.equals(employeeEditDTO.getAuthority(), AuthorityConstant.LOGOUT)){
            employee.setStatus(StatusConstant.DISABLE);
        }
        empMapper.updateEmpInfo(employee);
    }

    /**
     * 员工重置密码
     *
     * @param id
     */
    @Override
    public void resetPwd(Long id) {
        Employee employee = empMapper.getEmpById(id);
        String newPwd = DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes());
        employee.setPassword(newPwd);
        empMapper.updateEmpInfo(employee);
    }

    /**
     * 设置员工账号状态
     *
     * @param id
     * @param status
     */
    @Override
    public void resetStatus(Long id, Integer status) {
        Employee employee = empMapper.getEmpById(id);
        employee.setStatus(status);
        empMapper.updateEmpInfo(employee);
    }

    /**
     * 设置员工注销状态
     *
     * @param id
     * @param auth
     */
    @Override
    public void logoutEmp(Long id, Integer auth) {
        Employee employee = empMapper.getEmpById(id);
        if(Objects.equals(auth, AuthorityConstant.LOGOUT)){
            employee.setStatus(StatusConstant.DISABLE);
        }
        employee.setAuthority(auth);
        empMapper.updateEmpInfo(employee);
    }
}
